﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using TerhelesEloszto.Common;

namespace TerhelesEloszto.Engine
{
	/// <summary>
	/// Két tárgyat aszerint hasonlít össze, hogy egy oktató mennyire kedveli azokat.
	/// </summary>
	class TaskComparerByLike : IComparer<ITask>
	{
		private Teacher teacher;

		internal TaskComparerByLike( Teacher teacher )
		{
			this.teacher = teacher;
		}

		public int Compare( ITask obj1, ITask obj2 )
		{
			int like1 = teacher.GetStars( obj1 );
			int like2 = teacher.GetStars( obj2 );

			return like2 - like1;
		}
	}

	/// <summary>
	/// Oktatót reprezentáló interfész.
	/// </summary>
	class Teacher : ITeacher
	{
		#region ITeacher Members

		/// <summary>
		/// Az oktató szakmai preferenciái.
		/// </summary>
		public List<ISkill> Skills
		{
			get { return skills; }
			set { skills = value; }
		}

		/// <summary>
		/// Az oktató személyes preferenciái.
		/// </summary>
		public List<ILike> PersonalPreferences
		{
			get { return personalPreferences; }
			set { personalPreferences = value; }
		}

		/// <summary>
		/// Az oktató által elvégezhető feladatok lisátja.
		/// </summary>
		public List<ITask> AcceptableTasks
		{
			get { return acceptableTasks; }
			set { acceptableTasks = value; }
		}

		/// <summary>
		/// Az oktató órarendje.
		/// </summary>
		public ITimeTable PersonalTimeTable
		{
			get { return personalTimeTable; }
			set { personalTimeTable = value; }
		}

		/// <summary>
		/// Az oktató szakmai preferenciái.
		/// </summary>
		/// <returns>Az oktató szakmai preferenciái.</returns>
		public List<ISkill> GetSkills()
		{
			return Skills;
		}

		/// <summary>
		/// Az oktató személyes preferenciái.
		/// </summary>
		/// <returns>Az oktató személyes preferenciái.</returns>
		public List<ILike> GetPersonalPreferences()
		{
			return PersonalPreferences;
		}

		/// <summary>
		/// Az oktató által elvégezhető feladatok lisátja.
		/// </summary>
		/// <returns>Az oktató által elvégezhető feladatok lisátja.</returns>
		public List<ITask> GetAcceptableTasks()
		{
			return AcceptableTasks;
		}

		/// <summary>
		/// Az oktató órarendje.
		/// </summary>
		/// <returns>Az oktató órarendje.</returns>
		public ITimeTable GetPersonalTimeTable()
		{
			return PersonalTimeTable;
		}

		/// <summary>
		/// Megadja az oktató és a feladat viszonyát.
		/// </summary>
		/// <param name="t">A feladat.</param>
		/// <returns>A csillagok száma.</returns>
		public int GetStars( ITask t )
		{
			foreach( ILike l in personalPreferences )
			{
				if( l.Target.ID == t.ID )
				{
					return l.Stars;
				}
			}

			return 3;
		}


		#endregion

		#region IUser Members

		/// <summary>
		/// A felhaszáló neve.
		/// </summary>
		public string Name
		{
			get { return name; }
			set { name = value; }
		}

		/// <summary>
		/// A felhasználó e-mail címe.
		/// </summary>
		public string Email
		{
			get { return email; }
			set { email = value; }
		}

		/// <summary>
		/// A felhasználó neptun kódja (egyedi azonosító.)
		/// </summary>
		public string Neptun
		{
			get { return neptun; }
			set { neptun = value; }
		}

		/// <summary>
		/// A felhasználó jelszavának lenyomata.
		/// </summary>
		public int PasswordHash
		{
			get { return passwordHash; }
			set { passwordHash = value; }
		}

		#endregion

		/// <summary>
		/// Konstruktor linq entitázsból.
		/// </summary>
		/// <param name="userData">A linq entitázs.</param>
		internal Teacher( USER_DATA userData )
		{
			name = userData.NAME;
			email = userData.EMAIL;
			neptun = userData.NEPTUN;
			passwordHash = userData.PASSWORD;
		}

		/// <summary>
		/// Visszaadja az oktató által elvégezhető feladatok listájának egy részét.
		/// Az oktató személyes prefereciáinak megfelelő kedveltségi sorrendben adja vissza az első maxW súlyú elemet.
		/// Ha az oktató el tud végezni legalább egy feladatot, akkor listának is van legalább egy eleme.
		/// </summary>
		/// <param name="maxW">Az elemek maximális összsúlya.</param>
		/// <param name="currentSemester">A jelenlegi félév.</param>
		/// <returns>A feladatok.</returns>
		internal List<ITask> GetAcceptabeTasks( int maxW, SemesterType currentSemester )
		{
			List<ITask> allTasks = new List<ITask>();
			TaskComparerByLike tcbl = new TaskComparerByLike( this );

			List<ITask> currentAcceptableTasks =  acceptableTasks.Where(t => t.Semester == SemesterType.both || t.Semester == currentSemester ).ToList();
			foreach( ITask t in currentAcceptableTasks)
			{
				allTasks.Add( t );
			}

			allTasks.Sort( tcbl );

			int n = 0;
			int maxIndex = 0;

			if( allTasks.Count == 0 ) return new List<ITask>();

			for( int i = 0; i < allTasks.Count; i++ )
			{
				n += allTasks[i].GetHoursOnTwoAWeek();
				if( n > maxW )
				{
					break;
				}
				else
				{
					maxIndex = i;
				}
			}

			return allTasks.GetRange( 0, maxIndex + 1 );

		}

		private List<ISkill> skills;
		private List<ILike> personalPreferences;
		private List<ITask> acceptableTasks;
		private ITimeTable personalTimeTable;
		private string name;
		private string email;
		private string neptun;
		private int passwordHash;
	}
}
